/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = informix_request.c                                            */
/*  NOTE      = TDS协议解析                                                   */
/*  DATE      = 2014/05/27 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

#include "informix_core.h"
#include "informix_common.h"
#include "informix_sql_type.h"

#define INFORMIX_TRANS_BEGIN     "BEGIN"
#define INFORMIX_TRANS_COMMIT    "COMMMIT"
#define INFORMIX_TRANS_ROLLBACK  "ROLLBACK"

/*******************************************************************************
*  FUNC     :  设置sql值
*  ARGS     :  pp_sql (出力数据)
*           :  p_sql (入力数据)
*           :  pp_output (处理数据)
*  RTN      :  APM_L7_ANALYZE_SUCC
*              APM_L7_ANALYZE_FAIL
*  NOTE     :
*******************************************************************************/
static int __informix_set_sql(char **pp_sql, char *p_sql)
{
    int i_ret = APM_L7_ANALYZE_SUCC;

    if (*pp_sql == NULL)
    {
        *pp_sql = p_sql;
    }
    else
    {
        i_ret = informix_merge_string(*pp_sql, p_sql, pp_sql);
    }
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  将packet添加到对应的statement
*  ARGS     :  p_st_private (私有信息)
*  RTN      :  APM_L7_ANALYZE_SUCC
*              APM_L7_ANALYZE_FAIL
*  NOTE     :  p_st_private肯定不为NULL
*******************************************************************************/
static int __informix_get_statement(L7session_informix_private *p_st_private)
{
    Frlist_node *p_hash_node = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    L7_req_informix *p_st_req = p_st_private->p_st_req;

    /* 根据statement ID取得hash node */
    p_hash_node = frhash2_getLong(p_st_private->p_hash_prepare
                                  , p_st_req->l_cursor_id);

    /* 取得statement */
    p_st_statement = (Sql_statement *)FRLIST_GET_NODE_DATA(p_hash_node);
    if (p_st_statement == NULL)
    {
        frdbg("Get statement from hash failed");
        return APM_L7_ANALYZE_FAIL;
    }
    p_st_resultset = frdb_get_last_resultset(p_st_statement);

    /* 出力设置 */
    p_st_req->i_new_statement = FR_NO;
    p_st_req->p_st_statement = p_st_statement;
    p_st_req->p_st_resultset = p_st_resultset;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建statement
*  ARGS     :  p_st_conn (链接信息)
*           :  p_st_private (私有信息)
*  RTN      :  APM_L7_ANALYZE_SUCC
*              APM_L7_ANALYZE_FAIL
*  NOTE     :  p_st_private肯定不为NULL
*******************************************************************************/
static int __informix_create_statement(Conntrack *p_st_conn
                                       , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    unsigned long ul_req_sequence = 0;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    L7_req_informix *p_st_req = p_st_private->p_st_req;

    /* 如果一个packet里出现了两个sql statement当做错误处理 */
    if (p_st_req->p_st_statement)
    {
        frdbg("There are double sql statemet in one packet!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* create statement */
    p_st_statement = frdb_create_statement();
    if (p_st_statement == NULL)
    {
        frdbg("Call frdb_create_statement failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 设置sql statement */
    frdb_set_sql(p_st_statement, p_st_req->p_sql);
    p_st_req->p_sql = NULL;

    /* 创建结果集 */
    ul_req_sequence = frct_seq_increase(p_st_conn);
    p_st_resultset = frdb_create_resultset(ul_req_sequence);
    if (p_st_resultset == NULL)
    {
        frdbg("Call frdb_create_resultset failed!\n");
        frdb_statement_free(&p_st_statement);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 追加结果集到statement */
    i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
    if (i_ret != FR_SUCC)
    {
        frdbg("Insert resultset into statement failed!\n");
        frdb_statement_free(&p_st_statement);
        frdb_resultset_free(&p_st_resultset);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 出力设置 */
    p_st_req->i_new_statement = FR_YES;
    p_st_req->p_st_statement = p_st_statement;
    p_st_req->p_st_resultset = p_st_resultset;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建statement
*  ARGS     :  p_st_conn (链接信息)
*           :  p_st_private (私有信息)
*           :  i_req_type (request type)
*           :  p_sql (sql)
*  RTN      :  APM_L7_ANALYZE_SUCC
*              APM_L7_ANALYZE_FAIL
*  NOTE     :  p_st_private肯定不为NULL
*******************************************************************************/
static int __informix_set_statement(Conntrack *p_st_conn
                                    , L7session_informix_private *p_st_private
                                    , int i_req_type
                                    , const char *p_sql)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    char *p_sql_tmp = NULL;
    L7_req_informix *p_st_req = p_st_private->p_st_req;

    p_sql_tmp = frstrdup(p_sql);
    if (p_sql_tmp == NULL)
    {
        frdbg("create sql failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置sql语句 */
    i_ret = __informix_set_sql(&p_st_req->p_sql, p_sql_tmp);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("call __informix_set_sql failed!\n");
        frfree(p_sql_tmp);
        return APM_L7_ANALYZE_FAIL;
    }

    i_ret = __informix_create_statement(p_st_conn, p_st_private);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("call __informix_create_statement failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    p_st_req->i_req_type = i_req_type;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  上报request数据
*  ARGS     :  p_st_conn (链接信息)
*           :  p_st_private (私有信息)
*           :  i_req_type (request type)
*           :  p_sql (sql)
*  RTN      :  APM_L7_ANALYZE_SUCC
*              APM_L7_ANALYZE_FAIL
*  NOTE     :  p_st_private肯定不为NULL
*******************************************************************************/
static int __informix_report_req(Conntrack *p_st_conn
                                 , L7session_informix_private *p_st_private
                                 , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frreport_body_data *p_st_report_body = NULL;
    L7_req_informix *p_st_req = p_st_private->p_st_req;

    if (p_st_req == NULL || p_st_req->p_st_statement == NULL)
    {
        frdbg("statement is null！\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 创建report body */
    p_st_report_body = informix_new_report_body(p_st_conn, p_st_private->p_st_sess);
    /* 创建report body失败时，不释放做成的request */
    if (p_st_report_body == NULL)
    {
        frdbg("call informix_new_report_body failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 上报request数据 */
    i_ret = frdb_report_req2(p_st_conn, p_st_hash_report
                             , p_st_req->p_st_statement
                             , p_st_req->p_st_resultset
                             , &p_st_report_body);
    /* 上报request数据失败时，不释放做成的request */
    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_report_req2 failed!\n");
        frreport_body_free(&p_st_report_body);
        return APM_L7_ANALYZE_SUCC;
    }
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  解析LOGIN请求
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_login_req(Conntrack *p_st_conn
                            , L7session_informix_private *p_st_private)
{
    uint16_t u16_login_len = 0;
    uint16_t u16_skip_len = 0;
    uint16_t u16_flt_len = 0;
    uint16_t u16_ver_len = 0;
    uint16_t u16_user_len = 0;
    uint16_t u16_db_len = 0;
    uint16_t u16_env_count = 0;
    int i_flt_type = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    char *p_flt_str = NULL;
    char *p_user_name = NULL;
    char *p_db_name = NULL;
    char arr_version[32] = {0};
    L7session_informix *p_st_session = p_st_private->p_st_sess;
    L7_fragment_informix *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* Get login length */
    u16_login_len = bytebuff_remaining(p_st_data);
    if (u16_login_len < INFORMIX_HEADER_SIZE)
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 跳过login header */
    bytebuff_skip(p_st_data, INFORMIX_HEADER_SIZE - 2);
    u16_login_len -= INFORMIX_HEADER_SIZE - 2;

    /* skip short(100) + short(101) + short(61) */
    if (u16_login_len < 2 + 2 + 4 + 2)
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, 2 + 2 + 4);
    u16_login_len -= 2 + 2 + 4 + 2;

    /* get float type */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_flt_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u16_login_len < u16_flt_len + 2 + 12 + 2)
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_flt_str = (char *)frmalloc(u16_flt_len);
    if (p_flt_str == NULL)
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_flt_str, u16_flt_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_flt_str);
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
//    /* Set float type */
//    if (strncasecmp(p_flt_str, "IEEEM", 5) == 0)
//    {
//        i_flt_type = INFORMIX_FLT_IEEEM;
//    }
//    else if (strncasecmp(p_flt_str, "IEEEI", 5) == 0)
//    {
//        i_flt_type = INFORMIX_FLT_IEEEI;
//    }
//    else
//    {
//        frdbg("Float type is [%s]\n", p_flt_str);
//        frfree(p_flt_str);
//        return APM_L7_ANALYZE_FAIL;
//    }
    frfree(p_flt_str);
    u16_login_len -= u16_flt_len + 2 + 12 + 2;
    /* skip 2bytes short + 固定的12位 */
    bytebuff_skip(p_st_data, 2 + 12);

    /* get version */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_ver_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u16_login_len < u16_ver_len + 2
        || u16_ver_len >= sizeof(arr_version))
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    u16_login_len -= u16_ver_len + 2;
    i_ret = bytebuff_get_bytes(p_st_data, arr_version, u16_ver_len);
    if (i_ret != FR_SUCC)
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* todo set version ? */

    /* get length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_skip_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u16_login_len < u16_skip_len + 2)
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    u16_login_len -= u16_skip_len + 2;
    bytebuff_skip(p_st_data, u16_skip_len);

    /* get length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_skip_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u16_login_len < u16_skip_len + 4 + 4 + 4 + 2 + 2)
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    u16_login_len -= u16_skip_len + 4 + 4 + 4 + 2 + 2;
    bytebuff_skip(p_st_data, u16_skip_len + 4 + 4 + 4 + 2);

    /* get user name */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_user_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u16_login_len < u16_user_len + 2)
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_user_name = (char *)frmalloc(u16_user_len + 1);
    if (p_user_name == NULL)
    {
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_user_name, u16_user_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_user_name);
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_user_name[u16_user_len] = '\0';
    u16_login_len -= u16_user_len + 2;

    /* skip password */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_skip_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u16_login_len < u16_skip_len + 8 + 4 + 8 + 4 + 2 + 2 + 4 + 2)
    {
        frfree(p_user_name);
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    u16_login_len -= u16_skip_len + 8 + 4 +8 + 4 + 2 + 2 + 4 + 2;
    bytebuff_skip(p_st_data, u16_skip_len + 8 + 4 + 8 + 4 + 2 + 2 + 4);
    /* get dbname */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_db_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u16_login_len < u16_db_len + 2)
    {
        frfree(p_user_name);
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_db_name = (char *)frmalloc(u16_db_len + 1);
    if (p_db_name == NULL)
    {
        frfree(p_user_name);
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_db_name, u16_db_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_user_name);
        frfree(p_db_name);
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_db_name[u16_db_len] = '\0';
    u16_login_len -= u16_db_len + 2;
    /* skip env */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_skip_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u16_login_len < u16_skip_len + 2 * 6)
    {
        frfree(p_user_name);
        frfree(p_db_name);
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    u16_login_len -= u16_skip_len + 2 * 6;
    bytebuff_skip(p_st_data, u16_skip_len + 2 * 5);
    /* skip env */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_env_count, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        frfree(p_user_name);
        frfree(p_db_name);
        frdbg("Parse Login reuqest failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    while (u16_env_count--)
    {
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_skip_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC || u16_login_len < u16_skip_len + 2)
        {
            frfree(p_user_name);
            frfree(p_db_name);
            frdbg("Parse Login reuqest failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        u16_login_len -= u16_skip_len + 2;
        bytebuff_skip(p_st_data, u16_skip_len);
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_skip_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC || u16_login_len < u16_skip_len + 2)
        {
            frfree(p_user_name);
            frfree(p_db_name);
            frdbg("Parse Login reuqest failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        u16_login_len -= u16_skip_len + 2;
        bytebuff_skip(p_st_data, u16_skip_len);
    }

    /* 有一部分反编译出来缺失 todo */
    /* login packet以0x007F结尾 */
    //if (u16_login_len != 0)
    //{
    //    frdbg("Parse Login reuqest failed!\n");
    //    return APM_L7_ANALYZE_FAIL;
    //}
    //i_ret = bytebuff_get_short(p_st_data, 2, &u16_end, BYTE_BIG_ENDIAN);
    //if (i_ret != FR_SUCC || u16_end != 127)
    //{
    //    frdbg("Parse Login reuqest failed!\n");
    //    return APM_L7_ANALYZE_FAIL;
    //}

    p_st_session->i_flt_type = i_flt_type;
    if (p_st_session->p_db_user)
    {
        frfree(p_st_session->p_db_user);
    }
    p_st_session->p_db_user = p_user_name;
    if (p_st_session->p_db_name)
    {
        frfree(p_st_session->p_db_name);
    }
    p_st_session->p_db_name = p_db_name;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLISETSVPT
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_sqlisetsvpt(Conntrack *p_st_conn
                              , L7session_informix_private *p_st_private)

{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    i_ret = informix_skip_2byte_padded(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip padded data!\n");
        return i_ret;
    }
    i_ret = informix_skip_bytes(p_st_data, 2);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes data!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLIRELSVPT
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_sqlirelsvpt(Conntrack *p_st_conn
                              , L7session_informix_private *p_st_private)

{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    i_ret = informix_skip_2byte_padded(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip padded data!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLIRBACKSVPT
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_sqlirbacksvpt(Conntrack *p_st_conn
                                 , L7session_informix_private *p_st_private)

{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    i_ret = informix_skip_2byte_padded(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip padded data!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析COMMAND
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_command(Conntrack *p_st_conn
                           , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    unsigned int ui_size = 0;
    uint16_t u16_len = 0;
    char *p_sql = NULL;
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    if (bytebuff_remaining(p_st_data) < 2 + 2)
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* 跳过2byte */
    bytebuff_skip(p_st_data, 2);
    /* 版本未定猜测设置版本,一般sql不会超过65536 */
    if (p_st_sess->i_ver_get_flg == FR_NO)
    {
        i_ret = bytebuff_peek_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("get length failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (u16_len == 0)
        {
            p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX] = 1;
        }
    }
    /* 4byte长度 */
    if (p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX])
    {
        i_ret = informix_get_4byte_padded(p_st_data, &p_sql, &ui_size);
    }
    else
    {
        i_ret = informix_get_2byte_padded(p_st_data, &p_sql, &ui_size);
    }
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("get sql failed!\n");
        return i_ret;
    }

    p_st_req->i_req_type = INFORMIX_MSG_TP_COMMAND;
    /* 设置sql语句 */
    i_ret = __informix_set_sql(&p_st_req->p_sql, p_sql);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frfree(p_sql);
        frdbg("set sql failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 创建statement */
    i_ret = __informix_create_statement(p_st_conn, p_st_private);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("create statement failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析PREPARE
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_prepare(Conntrack *p_st_conn
                          , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    unsigned int ui_size = 0;
    char *p_sql = NULL;
    uint16_t u16_len = 0;
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* 长度check */
    if (bytebuff_remaining(p_st_data) < 2 + 2)
    {
        frdbg("need more length!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* 跳过2byte */
    bytebuff_skip(p_st_data, 2);
    /* 版本未定猜测设置版本,一般sql不会超过65536 */
    if (p_st_sess->i_ver_get_flg == FR_NO)
    {
        i_ret = bytebuff_peek_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("get length failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (u16_len == 0)
        {
            p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX] = 1;
        }
    }

    /* 2byte长度 */
    if (p_st_sess->arr_ver_info[INFORMIX_ONlINE5SER_IDX])
    {
        i_ret = informix_get_2byte_padded(p_st_data, &p_sql, &ui_size);
    }
    /* 4byte长度 */
    else if (p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX])
    {
        i_ret = informix_get_4byte_padded(p_st_data, &p_sql, &ui_size);
    }
    /* 2byte长度 */
    else
    {
        i_ret = informix_get_2byte_padded(p_st_data, &p_sql, &ui_size);
    }
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("get sql failed!\n");
        return i_ret;
    }
    /* 设定ONlINE5SER */
    if (p_st_sess->i_ver_get_flg == FR_NO && strcmp(p_sql, "NOCODING") == 0)
    {
        p_st_sess->arr_ver_info[INFORMIX_ONlINE5SER_IDX] = 1;
    }

    p_st_req->i_req_type = INFORMIX_MSG_TP_PREPARE;
    /* 设置sql语句 */
    i_ret = __informix_set_sql(&p_st_req->p_sql, p_sql);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frfree(p_sql);
        frdbg("set sql failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 创建statement */
    i_ret = __informix_create_statement(p_st_conn, p_st_private);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("Create statement failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析CURNAME
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_curname(Conntrack *p_st_conn
                          , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* skip cursorname */
    i_ret = informix_skip_2byte_padded(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("Skip cursor name failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析ID
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_id(Conntrack *p_st_conn
                      , L7session_informix_private *p_st_private)
{
    uint16_t u16_id = 0;
    int i_ret = FR_SUCC;
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    if (bytebuff_remaining(p_st_data) < 2)
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得statement ID */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_id, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        frdbg("call bytebuff_get_short failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_st_req->l_cursor_id = u16_id;

    /* 取得statement */
    i_ret = __informix_get_statement(p_st_private);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("Call __informix_get_statement failed!\n");
        return i_ret;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析BIND参数
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_bind(Conntrack *p_st_conn
                       , L7session_informix_private *p_st_private)
{
    int i_ret = FR_SUCC;
    //uint16_t u16_len = 0;
    uint16_t u16_count = 0;
    uint16_t u16_sql_type = 0;
    uint16_t u16_null_flg = 0;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;
    Frdata_field *p_st_value = NULL;
    Sql_field_bind *p_lst_bind = NULL;
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    if (bytebuff_remaining(p_st_data) < 2)
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得bind参数个数 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_count, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        frdbg("get bind count failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 创建bind list */
    p_lst_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
    if (p_lst_bind == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    memset(p_lst_bind, 0x0, sizeof(Sql_field_bind));

    /* 取得bind参数信息 */
    while (u16_count--)
    {
        if (bytebuff_remaining(p_st_data) < 2 + 2 + 2)
        {
            frdbg("need more data!\n");
            frdb_field_bind_free(&p_lst_bind);
            return APM_L7_ANALYZE_TODO;
        }
        /* 取得数据类型sql type */
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_sql_type, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("call bytebuff_get_short failed!\n");
            frdb_field_bind_free(&p_lst_bind);
            return APM_L7_ANALYZE_FAIL;
        }

        /* 需要跳过两个string */
        if (p_st_sess->arr_ver_info[INFORMIX_USVER_IDX]
            && u16_sql_type >= 18
            && u16_sql_type != INFORMIX_TYPE_BIGINT
            && u16_sql_type != INFORMIX_TYPE_BIGSERIAL)
        {
            i_ret = informix_skip_2byte_padded(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("skip extended owner failed!\n");
                frdb_field_bind_free(&p_lst_bind);
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = informix_skip_2byte_padded(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("skip extended type name failed!\n");
                frdb_field_bind_free(&p_lst_bind);
                return APM_L7_ANALYZE_FAIL;
            }
            if (bytebuff_remaining(p_st_data) < 2 + 2)
            {
                frdbg("need more data!\n");
                frdb_field_bind_free(&p_lst_bind);
                return APM_L7_ANALYZE_TODO;
            }
        }

        /* 取得NULL表示 */
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_null_flg, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC
            || (u16_null_flg != 0 && u16_null_flg != 0xFFFF
                && u16_null_flg != 0xFFFE))
        {
            frdbg("Get sql type null flag failed!\n");
            frdb_field_bind_free(&p_lst_bind);
            return APM_L7_ANALYZE_FAIL;
        }
        /* skip Encoded Length */
        bytebuff_skip(p_st_data, 2);
        switch (u16_sql_type)
        {
            case INFORMIX_TYPE_BOOL:
                i_ret = informix_convert_to_boolean(p_st_data, u16_null_flg
                                                   , &p_st_value);
                break;

            case INFORMIX_TYPE_CHAR:
            case INFORMIX_TYPE_VARCHAR:
            case INFORMIX_TYPE_NCHAR:
            case INFORMIX_TYPE_NVCHAR:
                i_ret = informix_convert_to_str(p_st_data, u16_null_flg
                                                , 2, &p_st_value);
                break;

            case INFORMIX_TYPE_SMALLINT:
                i_ret = informix_convert_to_int(p_st_data, u16_null_flg
                                               , 2, FR_NO, &p_st_value);
                break;

            case INFORMIX_TYPE_INT:
            case INFORMIX_TYPE_SERIAL:
                i_ret = informix_convert_to_int(p_st_data , u16_null_flg
                                               , 4, FR_NO, &p_st_value);
                break;

            case INFORMIX_TYPE_FLOAT:
                i_ret = informix_convert_to_float(p_st_data, (int)u16_null_flg, 8
                                                 , INFORMIX_FLT_IEEE_LO
                                                 , &p_st_value);
                break;

            case INFORMIX_TYPE_SMFLOAT:
                i_ret = informix_convert_to_float(p_st_data, (int)u16_null_flg, 4
                                                 , INFORMIX_FLT_IEEE_LO
                                                 , &p_st_value);
            break;

            case INFORMIX_TYPE_DECIMAL:
            case INFORMIX_TYPE_MONEY:
                i_ret = informix_convert_to_decimal(p_st_data, u16_null_flg
                                                   , &p_st_value);
                break;

            case INFORMIX_TYPE_DATE:
                i_ret = informix_convert_to_date(p_st_data, u16_null_flg
                                                , &p_st_value);
                break;

            case INFORMIX_TYPE_DATETIME:
                i_ret = informix_convert_to_datetime(p_st_data, u16_null_flg
                                                    , &p_st_value);
                break;

            case INFORMIX_TYPE_BYTE:
                p_value = frstrdup("BLOB");
                i_ret = informix_convert_to_large(p_st_data, u16_null_flg
                                                 , p_value
                                                 , &p_st_value);
                break;

            case INFORMIX_TYPE_TEXT:
                p_value = frstrdup("CLOB");
                i_ret = informix_convert_to_large(p_st_data, u16_null_flg
                                                  , p_value
                                                  , &p_st_value);
                break;

            case INFORMIX_TYPE_INT8:
            case INFORMIX_TYPE_SERIAL8:
                if (u16_null_flg == 0)
                {
                    i_ret = informix_convert_to_int(p_st_data, u16_null_flg, 8, FR_NO
                                                   , &p_st_value);
                }
                else
                {
                    i_ret = frtds_create_param(NULL, FRINT, &p_st_value);
                }
                break;

            case INFORMIX_TYPE_LVARCHAR:
                if (u16_null_flg == 0)
                {
                    /* todo 反编译是8 */
                    i_ret = informix_convert_to_str(p_st_data, u16_null_flg, 4
                                                    , &p_st_value);
                }
                else
                {
                    i_ret = frtds_create_param(NULL, FRSHORT, &p_st_value);
                }
                break;

            case INFORMIX_TYPE_SENDRECV:
            case INFORMIX_TYPE_BLOB://need to check todo
            case INFORMIX_TYPE_CLOB://need to check todo
                i_ret = informix_convert_to_lob(p_st_data, u16_null_flg
                                               , &p_st_value);
                break;

            case INFORMIX_TYPE_NULL:
            case INFORMIX_TYPE_INTERVAL:
            case INFORMIX_TYPE_SET:
            case INFORMIX_TYPE_MULTISET:
            case INFORMIX_TYPE_LIST:
            case INFORMIX_TYPE_ROW:
            case INFORMIX_TYPE_COLLECTION:
            case INFORMIX_TYPE_ROWREF:
            case INFORMIX_TYPE_UDTVAR:
            case INFORMIX_TYPE_UDTFIXED:
            case INFORMIX_TYPE_REFSER8:
            case INFORMIX_TYPE_IMPEXP:
            case INFORMIX_TYPE_IMPEXPBIN:
            case INFORMIX_TYPE_SQLUDRDEFAULT:
            case INFORMIX_TYPE_UNKNOWN:
            case INFORMIX_TYPE_MAX:
                if (u16_null_flg == 0)
                {
                    //parse todo
                    frdbg("unsupport SQL type[%d]!\n", u16_sql_type);
                    i_ret = APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    i_ret = frtds_create_param(NULL, FRSHORT, &p_st_value);
                }
                break;

            default:
                frdbg("incorrect SQL type[%d]!\n", u16_sql_type);
                i_ret = APM_L7_ANALYZE_FAIL;
                break;
        }

        /* 解析结果判定 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            if (p_value)
            {
                frfree(p_value);
            }
            frdb_field_bind_free(&p_lst_bind);
            return i_ret;
        }
        p_value = NULL;

        p_st_node = frlist_node_create(p_st_value);
        if (p_st_node == NULL)
        {
            frdbg("Create node failed\n");
            frdb_field_bind_free(&p_lst_bind);
            informix_free_param(&p_st_value);
            return APM_L7_ANALYZE_FAIL;
        }
        frlist_push(&p_lst_bind->st_field_list, p_st_node);
    }

    /* 设置bind参数 */
    if (p_st_req && p_st_req->i_add_bind_flg == FR_YES
         && p_st_req->p_st_resultset)
    {
        p_st_node = frlist_node_create(p_lst_bind);
        if (p_st_node == NULL)
        {
            frdbg("Create node failed\n");
            frdb_field_bind_free(&p_lst_bind);
            return APM_L7_ANALYZE_FAIL;
        }
        frlist_push(&p_st_req->p_st_resultset->st_bind_list, p_st_node);
    }
    else
    {
        if (p_st_req && p_st_req->i_add_bind_flg == FR_YES)
        {
            frdbg("resultset is null, attention\n");
        }
        else
        {
            frdbg("no need to add bind list to statement!\n");
        }
        frdb_field_bind_free(&p_lst_bind);
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析NFETCH
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_nfetch(Conntrack *p_st_conn
                         , L7session_informix_private *p_st_private)
{
    int i_ret = FR_SUCC;
    uint16_t u16_len = 0;
    uint16_t u16_value = 0;
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    if (p_st_sess->i_ver_get_flg == FR_NO)
    {
        if (bytebuff_remaining(p_st_data) < 2)
        {
            frdbg("need more data!\n");
            return APM_L7_ANALYZE_TODO;
        }
        /* 一般不会超过65536 */
        i_ret = bytebuff_peek_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("peek length data!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (u16_len == 0)
        {
            i_ret = informix_skip_bytes(p_st_data, 4);
        }
        else
        {
            i_ret = informix_skip_bytes(p_st_data, 2);
        }
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("skip bytes failed!\n");
            return i_ret;
        }
        if (bytebuff_remaining(p_st_data) < 2)
        {
            frdbg("need more data!\n");
            return APM_L7_ANALYZE_TODO;
        }
        /* 有肯定是0 */
        i_ret = bytebuff_peek_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("peek length data!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (u16_len == 0)
        {
            bytebuff_skip(p_st_data, 2);
        }
        p_st_req->i_req_type = INFORMIX_MSG_TP_NFETCH;
        return APM_L7_ANALYZE_SUCC;
    }

    if (p_st_sess->arr_ver_info[INFORMIX_XPSVER8_40_IDX]
        || p_st_sess->arr_ver_info[INFORMIX_2GBFETCHBUFFERSUPPORTED_IDX])
    {
        i_ret = informix_skip_bytes(p_st_data, 4);
    }
    else
    {
        i_ret = informix_skip_bytes(p_st_data, 2);
    }
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    if (p_st_sess->arr_ver_info[INFORMIX_90303_IDX]
        || p_st_sess->arr_ver_info[INFORMIX_IDX9_IDX])
    {
        if (bytebuff_remaining(p_st_data) < 2)
        {
            frdbg("need more data!\n");
            return APM_L7_ANALYZE_TODO;
        }
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC || u16_value != 0)
        {
            frdbg("get value failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (i_ret != FR_SUCC || u16_value != 0)
        {
            frdbg("get value failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
    }

    p_st_req->i_req_type = INFORMIX_MSG_TP_NFETCH;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析ERROR
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_err_req(Conntrack *p_st_conn
                           , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint32_t u32_len = 0;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;

    i_ret = informix_skip_bytes(p_st_data, 2 + 2 + 2);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    if (p_st_sess->i_ver_get_flg == FR_NO)
    {
        i_ret = bytebuff_peek_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("get length failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (u32_len == 0)
        {
            i_ret = informix_skip_bytes(p_st_data, 2 + 2);
        }
        else
        {
            i_ret = informix_skip_bytes(p_st_data, 2);
        }
    }
    else if (p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX])
    {
        i_ret = informix_skip_bytes(p_st_data, 2 + 2);
    }
    else
    {
        i_ret = informix_skip_bytes(p_st_data, 2);
    }
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析PUT
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_put(Conntrack *p_st_conn
                      , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    char *p_sql = NULL;
    uint16_t u16_len = 0;
    unsigned int ui_size = 0;
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    if (p_st_sess->arr_ver_info[INFORMIX_USVER_IDX])
    {
        i_ret = informix_skip_bytes(p_st_data, 4);
    }
    else
    {
        i_ret = informix_skip_bytes(p_st_data, 2);
    }
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    if (p_st_sess->i_ver_get_flg == FR_NO)
    {
        i_ret = bytebuff_peek_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("get length failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (u16_len == 0)
        {
            p_st_sess->arr_ver_info[INFORMIX_XPSVER8_40_IDX] = 1;
        }
    }

    /* 取得sql */
    if (p_st_sess->arr_ver_info[INFORMIX_XPSVER8_40_IDX])
    {
        i_ret = informix_get_4byte_padded(p_st_data, &p_sql, &ui_size);
    }
    else
    {
        i_ret = informix_get_2byte_padded(p_st_data, &p_sql, &ui_size);
    }
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("get sql failed!\n");
        return i_ret;
    }

    p_st_req->i_req_type = INFORMIX_MSG_TP_PUT;
    /* 设置sql语句 */
    i_ret = __informix_set_sql(&p_st_req->p_sql, p_sql);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frfree(p_sql);
        frdbg("set sql failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 创建statement */
    i_ret = __informix_create_statement(p_st_conn, p_st_private);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("Create statement failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析BBIND
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_rbwork(Conntrack *p_st_conn
                         , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    i_ret = informix_skip_bytes(p_st_data, 2);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SFETCH
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_sfetch(Conntrack *p_st_conn
                         , L7session_informix_private *p_st_private)
{
    uint16_t u16_len = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    i_ret = informix_skip_bytes(p_st_data, 2 + 4);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    if (p_st_sess->i_ver_get_flg == FR_NO)
    {
        i_ret = bytebuff_peek_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("get length failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (u16_len == 0)
        {
            i_ret = informix_skip_bytes(p_st_data, 4);
        }
        else
        {
            i_ret = informix_skip_bytes(p_st_data, 2);
        }
    }
    else if (p_st_sess->arr_ver_info[INFORMIX_XPSVER8_40_IDX]
            || p_st_sess->arr_ver_info[INFORMIX_2GBFETCHBUFFERSUPPORTED_IDX])
    {
        i_ret = informix_skip_bytes(p_st_data, 4);
    }
    else
    {
        i_ret = informix_skip_bytes(p_st_data, 2);
    }
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    p_st_req->i_req_type = INFORMIX_MSG_TP_SFETCH;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析BBIND
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_bbind(Conntrack *p_st_conn
                        , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    i_ret = informix_skip_bytes(p_st_data, 2);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析DBOPEN
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_dbopen(Conntrack *p_st_conn
                         , L7session_informix_private *p_st_private)
{
    int i_ret = FR_SUCC;
    unsigned int ui_size = 0;
    char *p_dbname = NULL;
    L7session_informix *p_st_session = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* check长度是否足够 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* get dbname */
    i_ret = informix_get_2byte_padded(p_st_data, &p_dbname, &ui_size);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("get dbname failed!\n");
        return i_ret;
    }

    i_ret = informix_skip_bytes(p_st_data, 2);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    /* set dbname */
    if (p_st_session->p_db_name)
    {
        frfree(p_st_session->p_db_name);
    }
    p_st_session->p_db_name = p_dbname;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析BLOB
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_blob_req(Conntrack *p_st_conn
                            , L7session_informix_private *p_st_private)
{
    int i_ret = FR_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    i_ret = informix_skip_2byte_padded(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip blob failed!\n");
        return i_ret;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析INFO
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_info_req(Conntrack *p_st_conn
                            , L7session_informix_private *p_st_private)
{
    uint16_t u16_count = 0;
    uint16_t u16_value = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_fragment_informix *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* check长度是否足够 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得value */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        frdbg("get value failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    switch (u16_value)
    {
        case 0:
            i_ret = informix_skip_bytes(p_st_data, 2);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("skip bytes failed!\n");
                return i_ret;
            }
            break;

        case 1:
            i_ret = informix_skip_bytes(p_st_data, 2 + 2);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("skip bytes failed!\n");
                return i_ret;
            }
            break;

        case 6:
            /* check长度是否足够 */
            if (bytebuff_remaining(p_st_data) < 2 + 2 + 2)
            {
                frdbg("need more data!\n");
                return APM_L7_ANALYZE_TODO;
            }
            bytebuff_skip(p_st_data, 2 + 2);
            /* 取得env count数 */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_count, BYTE_BIG_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                frdbg("call bytebuff_get_short failed!\n");
                return APM_L7_ANALYZE_FAIL;
            }
            while (u16_count--)
            {
                /* 跳过env */
                i_ret = informix_skip_2byte_padded(p_st_data);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("skip padded failed!\n");
                    return i_ret;
                }
            }

            i_ret = informix_skip_bytes(p_st_data, 2 + 2);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("skip bytes failed!\n");
                return i_ret;
            }
            break;

        default:
            frdbg("Parse info failed\n");
            return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析LODATA
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_lodata_req(Conntrack *p_st_conn
                             , L7session_informix_private *p_st_private)
{
    uint16_t u16_len = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_fragment_informix *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* check长度是否足够 */
    if (bytebuff_remaining(p_st_data) < 2 + 2 + 4 + 2)
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得长度 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        frdbg("call bytebuff_get_short failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, 2 + 4 + 2);

    /* todo 这部分反编译中没有，根据数据包预测加的 */
    i_ret = informix_skip_2byte_padded(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("call informix_skip_2byte_padded failed!\n");
        return i_ret;
    }

    if (u16_len == 1)
    {
        i_ret = informix_skip_bytes(p_st_data, 10 + 2);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("skip bytes failed!\n");
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析RET
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_ret(Conntrack *p_st_conn
                       , L7session_informix_private *p_st_private)
{
    uint16_t u16_type = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint16_t u16_rows = 0;
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;
    Frlist_header *p_lst_metadata = NULL;
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    Sql_statement *p_st_statement = p_st_req->p_st_statement;
    L7_fragment_informix *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    if (p_st_statement == NULL)
    {
        frdbg("Statement is null\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_lst_metadata = &p_st_statement->st_metadata_column;

    /* check长度是否足够 */
    if (bytebuff_remaining(p_st_data) < 2 + 2)
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* skip first 2byte */
    bytebuff_skip(p_st_data, 2);
    /* get cloum count */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_rows, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || frlist_size(p_lst_metadata) != u16_rows)
    {
        frdbg("Call bytebuff_get_short failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    p_st_node = FRLIST_FIRST_NODE(p_lst_metadata);
    while (p_st_node)
    {
        /* check长度是否足够 */
        if (bytebuff_remaining(p_st_data) < 2)
        {
            frdbg("need more data!\n");
            return APM_L7_ANALYZE_TODO;
        }
        /* 取得sql type*/
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_type, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("get statement ID failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }

        p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
        if (p_st_metadata->i_data_type > 18 && p_st_metadata->i_data_type != 52
            && p_st_metadata->i_data_type != 53
            && ((u16_type != 13 && u16_type != 16) || u16_type == 43))
        {
            /* 跳过ExtendedOwnerName and ExtendedName */
            i_ret = informix_skip_2byte_padded(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("Call informix_skip_2byte_padded failed!\n");
                return i_ret;
            }
            i_ret = informix_skip_2byte_padded(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("Call informix_skip_2byte_padded failed!\n");
                return i_ret;
            }
        }
        i_ret = informix_skip_bytes(p_st_data, 4);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("skip bytes failed!\n");
            return i_ret;
        }
        /* 下一个 */
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析GETROUTINE
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_getroutine_req(Conntrack *p_st_conn
                                 , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    char arr_2byte_end[2] = {0};
    uint8_t u8_type = 0;
    uint16_t u16_value = 0;
    uint32_t u32_len = 0;
    uint16_t u16_len = 0;
    unsigned int ui_position = 0;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    if (p_st_sess->i_ver_get_flg == FR_NO)
    {
        ui_position = bytebuff_getPosition(p_st_data);
        if (bytebuff_remaining(p_st_data) < 2)
        {
            frdbg("need more data!\n");
            return APM_L7_ANALYZE_TODO;
        }
        i_ret = bytebuff_get_bytes_at(p_st_data, bytebuff_length(p_st_data) - 2
                                      , 2, arr_2byte_end);
        if (i_ret != FR_SUCC)
        {
            frdbg("get end value data!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (memcmp(arr_2byte_end, "\x00\x0c", 2) != 0)
        {
            frdbg("need more data!\n");
            return APM_L7_ANALYZE_TODO;
        }

        bytebuff_get_char(p_st_data, &u8_type);
        if (u8_type == 1)
        {
            if (bytebuff_remaining(p_st_data) < 4)
            {
                frdbg("need more data!\n");
                return APM_L7_ANALYZE_TODO;
            }

            i_ret = bytebuff_peek_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                frdbg("get length data!\n");
                return APM_L7_ANALYZE_FAIL;
            }
            else if (bytebuff_remaining(p_st_data) == 2 + u16_len + u16_len%2 + 4 + 2 + 2)
            {
                bytebuff_skip(p_st_data, 2 + u16_len + u16_len%2 + 4);
                i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    frdbg("get value data!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                else if (u16_value == 0 || u16_value == 1)
                {
                    p_st_sess->arr_ver_info[INFORMIX_NAMEDPARAMETERSSUPPORTED_IDX] = 1;
                    p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX] = 0;
                    return APM_L7_ANALYZE_SUCC;
                }
            }
            else
            {
                i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    frdbg("get length data!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                if (u32_len + u32_len%2 + 4 + 2 + 2 == (unsigned int)bytebuff_remaining(p_st_data))
                {
                    bytebuff_skip(p_st_data, u32_len + u32_len%2 + 4);
                    i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("get value data!\n");
                        return APM_L7_ANALYZE_FAIL;
                    }
                    else if (u16_value == 0 || u16_value == 1)
                    {
                        p_st_sess->arr_ver_info[INFORMIX_NAMEDPARAMETERSSUPPORTED_IDX] = 1;
                        p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX] = 1;
                        return APM_L7_ANALYZE_SUCC;
                    }
                }
            }
        }
        else if (u8_type == 0)
        {
            if (bytebuff_remaining(p_st_data) < 4)
            {
                frdbg("need more data!\n");
                return APM_L7_ANALYZE_TODO;
            }

            i_ret = bytebuff_peek_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                frdbg("get length data!\n");
                return APM_L7_ANALYZE_FAIL;
            }
            else if (bytebuff_remaining(p_st_data) == 2 + u16_len + u16_len%2 + 2 + 2)
            {
                bytebuff_skip(p_st_data, 2 + u16_len + u16_len%2);
                i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    frdbg("get value data!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                else if (u16_value == 0 || u16_value == 1)
                {
                    p_st_sess->arr_ver_info[INFORMIX_NAMEDPARAMETERSSUPPORTED_IDX] = 1;
                    p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX] = 0;
                    return APM_L7_ANALYZE_SUCC;
                }
            }
            else
            {
                i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    frdbg("get length data!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                if (u32_len + u32_len%2 + 2 + 2 == (unsigned int)bytebuff_remaining(p_st_data))
                {
                    bytebuff_skip(p_st_data, u32_len + u32_len%2);
                    i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("get value data!\n");
                        return APM_L7_ANALYZE_FAIL;
                    }
                    else if (u16_value == 0 || u16_value == 1)
                    {
                        p_st_sess->arr_ver_info[INFORMIX_NAMEDPARAMETERSSUPPORTED_IDX] = 1;
                        p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX] = 1;
                        return APM_L7_ANALYZE_SUCC;
                    }
                }
            }
        }
        bytebuff_setPosition(p_st_data, ui_position);
        if (bytebuff_remaining(p_st_data) < 4)
        {
            frdbg("need more data!\n");
            return APM_L7_ANALYZE_TODO;
        }
        i_ret = bytebuff_peek_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("get length data!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        else if (bytebuff_remaining(p_st_data) == 2 + u16_len + u16_len%2 + 2 + 2)
        {
            bytebuff_skip(p_st_data, 2 + u16_len + u16_len%2);
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                frdbg("get value data!\n");
                return APM_L7_ANALYZE_FAIL;
            }
            else if (u16_value == 0 || u16_value == 1)
            {
                p_st_sess->arr_ver_info[INFORMIX_NAMEDPARAMETERSSUPPORTED_IDX] = 0;
                p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX] = 0;
                return APM_L7_ANALYZE_SUCC;
            }
        }
        else
        {
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                frdbg("get length data!\n");
                return APM_L7_ANALYZE_FAIL;
            }
            if (u32_len + u32_len%2 + 2 + 2 == (unsigned int)bytebuff_remaining(p_st_data))
            {
                bytebuff_skip(p_st_data, u32_len + u32_len%2);
                i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    frdbg("get value data!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                else if (u16_value == 0 || u16_value == 1)
                {
                    p_st_sess->arr_ver_info[INFORMIX_NAMEDPARAMETERSSUPPORTED_IDX] = 0;
                    p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX] = 1;
                    return APM_L7_ANALYZE_SUCC;
                }
            }
        }
        frdbg("parse failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    if (p_st_sess->arr_ver_info[INFORMIX_NAMEDPARAMETERSSUPPORTED_IDX])
    {
        i_ret = informix_skip_bytes(p_st_data, 1);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("skip bytes failed!\n");
            return i_ret;
        }
    }

    if (p_st_sess->arr_ver_info[INFORMIX_REMOVE64KLIMITSUPPORTED_IDX])
    {
        i_ret = informix_skip_4byte_padded(p_st_data);
    }
    else
    {
        i_ret = informix_skip_2byte_padded(p_st_data);
    }
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip padded failed!\n");
        return i_ret;
    }
    i_ret = informix_skip_bytes(p_st_data, 1);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析EXFPROUTINE
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_exfproutine(Conntrack *p_st_conn
                              , L7session_informix_private *p_st_private)
{
    int i_ret = FR_SUCC;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    if (p_st_sess->arr_ver_info[INFORMIX_NAMEDPARAMETERSSUPPORTED_IDX])
    {
        i_ret = informix_skip_2byte_padded(p_st_data);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("call informix_skip_2byte_padded failed!\n");
            return i_ret;
        }
    }

    /* skip 8byte */
    i_ret = informix_skip_bytes(p_st_data, 4 + 2 + 2);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析FPARAM
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_fparam_req(Conntrack *p_st_conn
                             , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* skip 13byte */
    i_ret = informix_skip_bytes(p_st_data, 8 + 4 + 1);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析READ
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_read(Conntrack *p_st_conn
                       , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* 不确定 */
    frdbg("please attention read message!\n");
    i_ret = informix_skip_2byte_padded(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip padded failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析WRITE
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_write(Conntrack *p_st_conn
                          , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* skip 4byte */
    i_ret = informix_skip_bytes(p_st_data, 4);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析protocols
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_protocols_req(Conntrack *p_st_conn
                                , L7session_informix_private *p_st_private)
{
    int i_ret = FR_SUCC;
    uint16_t u16_len = 0;
    unsigned int ui_size = 0;
    char *p_output = NULL;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* 取得protocols */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        frdbg("get protocols length failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    i_ret = informix_read_padded(p_st_data, u16_len, &p_output, &ui_size);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("get protocols failed!\n");
        return i_ret;
    }

    /* 设置client version */
    p_st_sess->ui_req_ver_size = u16_len;
    if (p_st_sess->p_req_ver)
    {
        frfree(p_st_sess->p_req_ver);
    }
    p_st_sess->p_req_ver = p_output;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析RESPONSE
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_response_req(Conntrack *p_st_conn
                               , L7session_informix_private *p_st_private)
{
    int i_ret = FR_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* skip */
    frdbg("please attention RESPONSE message!\n");
    i_ret = informix_skip_2byte_padded(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip padded data!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析CFPDESCRIBE
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_cfpdescribe(Conntrack *p_st_conn
                              , L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7session_informix *p_st_sess = p_st_private->p_st_sess;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    if (p_st_sess->arr_ver_info[INFORMIX_NAMEDPARAMETERSSUPPORTED_IDX])
    {
        /* 跳过1byte */
        i_ret = informix_skip_bytes(p_st_data, 1);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("skip bytes failed!\n");
            return i_ret;
        }
    }
    else
    {
        /* 跳过2byte */
        i_ret = informix_skip_bytes(p_st_data, 2);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("skip bytes failed!\n");
            return i_ret;
        }
    }

    /* skip 4bytes */
    i_ret = informix_skip_bytes(p_st_data, 4);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SGKPREPARE
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_sgkprepare(Conntrack *p_st_conn
                              , L7session_informix_private *p_st_private)

{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint16_t u16_type = 0;
    uint16_t u16_count = 0;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* 取得类型 */
    if (bytebuff_remaining(p_st_data) < 2 + 2)
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_type, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        frdbg("Get type failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得count */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_count, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        frdbg("Get count failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    if (u16_type == 2)
    {
        while (u16_count--)
        {
            /* skip SGK length */
            i_ret = informix_skip_bytes(p_st_data, 2);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("skip bytes failed!\n");
                return i_ret;
            }
        }
    }
    else if (u16_type == 3)
    {
        while (u16_count--)
        {
            /* skip SGK name */
            i_ret = informix_skip_2byte_padded(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("skip SGK name data!\n");
                return i_ret;
            }
        }
    }
    else
    {
        frdbg("unkonw type!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析request
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*           :  p_st_hash_report(保存Frreport_data)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_request(Conntrack *p_st_conn
                           , L7session_informix_private *p_st_private
                           , Frhash_header *p_st_hash_report)
{
    int i_ret = FR_SUCC;
    int i_add_bind = FR_YES;
    uint16_t u16_2byte_head = 0;
    unsigned char arr_2byte_end[2] = {0};
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    L7_fragment_informix *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    bytebuff_setPosition(p_st_data, p_st_fragment->ui_parsed_index);
    /* 取得头部两位的值 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        frdbg("need more length!\n");
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_2byte_head, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        frdbg("Get message type failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 判断是否是login */
    if (p_st_req == NULL && u16_2byte_head > 2
        && bytebuff_remaining(p_st_data) == u16_2byte_head - 2)
    {
        /* 取得末尾的两位进一步确认是否是LOGIN */
        i_ret = bytebuff_get_bytes_at(p_st_data, u16_2byte_head - 2
                                      , 2, arr_2byte_end);
        if (i_ret != FR_SUCC)
        {
            frdbg("get last 2bytes failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        /* 如果以[007F]结尾就认为这是login */
        if (memcmp(arr_2byte_end, "\x00\x7F", 2) == 0)
        {
            i_ret = informix_parse_login_req(p_st_conn, p_st_private);
            if (i_ret == APM_L7_ANALYZE_SUCC)
            {
                p_st_private->p_st_req = informix_create_request();
                if (p_st_private->p_st_req == NULL)
                {
                    frdbg("create request failed\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                p_st_private->p_st_req->i_req_type = INFORMIX_MSG_TP_LOGIN;
                informix_init_fragment(p_st_fragment);
                p_st_fragment->i_need_req_resp = INFORMIX_DIRECT_RESPONSE;
                i_ret = APM_L7_ANALYZE_SET_LOGIN(APM_L7_ANALYZE_SUCC);
                return APM_L7_ANALYZE_SET_REQ(i_ret);
            }
            /* LOGIN解析失败当作普通的请求 */
            else
            {
                frdbg("that packet is not login!\n");
                bytebuff_setPosition(p_st_data, p_st_fragment->ui_parsed_index + 2);
            }
        }
    }

    /*
    *  GETROUTINE和EXFPROUTINE时无法用cursor ID取得对应的statement,
    *  实际应用中是紧接着上个request和response的内容
    */
    if (p_st_fragment->ui_parsed_index == 0
        && p_st_private->p_st_resp && p_st_private->p_st_req
        && u16_2byte_head != 101 && u16_2byte_head != 102
        && u16_2byte_head != 103 && u16_2byte_head != 97)
    {
        informix_destroy_request(&p_st_private->p_st_req);
        informix_destroy_response(&p_st_private->p_st_resp);
    }
    else if (u16_2byte_head == 101 || u16_2byte_head == 102
             || u16_2byte_head == 103 || u16_2byte_head == 97)
    {
        i_add_bind = FR_NO;
    }

    /* 创建request */
    p_st_req = p_st_private->p_st_req;
    if (p_st_req == NULL)
    {
        p_st_req = informix_create_request();
        if (p_st_req == NULL)
        {
            frdbg("create request failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        p_st_private->p_st_req = p_st_req;
    }

    if (p_st_fragment->i_need_req_resp == INFORMIX_DIRECT_RESPONSE)
    {
        /* 连续连个request, 销毁之前request的数据 */
        frdbg("Thers is a request before!\n");
        informix_int_request(p_st_req);
    }
    p_st_req->i_add_bind_flg = i_add_bind;

    /* 解析 */
    while (u16_2byte_head != INFORMIX_MSG_TP_EOT)
    {
        switch (u16_2byte_head)
        {
            case INFORMIX_MSG_TP_COMMAND: /* 直接上报 */
                i_ret = informix_parse_command(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_PREPARE:
                i_ret = informix_parse_prepare(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_CURNAME:
                i_ret = informix_parse_curname(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_ID:
                i_ret = informix_parse_id(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_BIND:
                i_ret = informix_parse_bind(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_NFETCH:
                i_ret = informix_parse_nfetch(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_ERR:
                i_ret = informix_parse_err_req(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_PUT:
                i_ret = informix_parse_put(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_RBWORK:
                i_ret = informix_parse_rbwork(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_SFETCH:
                i_ret = informix_parse_sfetch(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_DBLIST:
                i_ret = __informix_set_statement(p_st_conn, p_st_private
                                                , u16_2byte_head, "GetDBList");
                break;

            case INFORMIX_MSG_TP_BEGIN:
                i_ret = __informix_set_statement(p_st_conn, p_st_private
                                                , u16_2byte_head, "BEGIN");
                break;

            case INFORMIX_MSG_TP_DBOPEN: //(24)36
                i_ret = informix_parse_dbopen(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_BLOB:
                i_ret = informix_parse_blob_req(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_BBIND:
                i_ret = informix_parse_bbind(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_XCOMMIT:
                i_ret = __informix_set_statement(p_st_conn, p_st_private
                                                , u16_2byte_head, "COMMIT");
                break;

            case INFORMIX_MSG_TP_XROLLBACK:
                i_ret = __informix_set_statement(p_st_conn, p_st_private
                                                , u16_2byte_head, "ROLLBACK");
                break;

            case INFORMIX_MSG_TP_INFO: //(51)81
                i_ret = informix_parse_info_req(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_LODATA:  //(61)97
                i_ret = informix_parse_lodata_req(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_RET_TYPE: //(64)100
                i_ret = informix_parse_ret(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_GETROUTINE: //(65)101
                i_ret = informix_parse_getroutine_req(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_EXFPROUTINE: //(66)102
                i_ret = informix_parse_exfproutine(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_FPARAM:
                i_ret = informix_parse_fparam_req(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_FILE_READ:
                i_ret = informix_parse_read(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_FILE_WRITE:
                i_ret = informix_parse_write(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_PROTOCOLS: //(7E)126
                i_ret = informix_parse_protocols_req(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_RESPONSE:
                i_ret = informix_parse_response_req(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_CFPDESCRIBE:
                i_ret = informix_parse_cfpdescribe(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_SGKPREPARE:
                i_ret = informix_parse_sgkprepare(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_SQLISETSVPT:
                i_ret = informix_parse_sqlisetsvpt(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_SQLIRELSVPT:
                i_ret = informix_parse_sqlirelsvpt(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_SQLIRBACKSVPT:
                i_ret = informix_parse_sqlirbacksvpt(p_st_conn, p_st_private);
                break;

            case INFORMIX_MSG_TP_EXECUTE: /* 上报 */
                p_st_req->i_req_type = u16_2byte_head;

            case INFORMIX_MSG_TP_RELEASE:
            case INFORMIX_MSG_TP_CLOSE:
            case INFORMIX_MSG_TP_DBCLOSE: /* 关闭当前DB */
            case INFORMIX_MSG_TP_EXIT:    /* 关闭连接 */
            case INFORMIX_MSG_TP_OPEN:    /* Query open */

            case INFORMIX_MSG_TP_DESCBIND: //todo 反编译没看到
            case INFORMIX_MSG_TP_CMMTWORK:
            case INFORMIX_MSG_TP_NDESCRIBE:
            case INFORMIX_MSG_TP_SCROLL:
            case INFORMIX_MSG_TP_FETCHBLOB:
            case INFORMIX_MSG_TP_FERR:
            case INFORMIX_MSG_TP_HOLD:
            case INFORMIX_MSG_TP_WANTDONE:
            case INFORMIX_MSG_TP_VERSION:
            case INFORMIX_MSG_TP_AUTOFREE:
            case INFORMIX_MSG_TP_CIDESCRIBE:
            case INFORMIX_MSG_TP_ACK:
            case INFORMIX_MSG_TP_BATCHSTART:
            case INFORMIX_MSG_TP_BATCHEND:
                i_ret = APM_L7_ANALYZE_SUCC;
                break;

            default:
                frdbg("Unkonw support message type:[%d]!\n", u16_2byte_head);
                return APM_L7_ANALYZE_FAIL;
        }

        /* 解析结果处理 */
        if (i_ret == APM_L7_ANALYZE_SUCC)
        {
            p_st_fragment->ui_parsed_index = bytebuff_getPosition(p_st_data);
        }
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            frdbg("Parse token:[%d] need more data!\n", u16_2byte_head);
            return APM_L7_ANALYZE_TODO;
        }
        else
        {
            frdbg("Parse message type:[%d] faied!\n", u16_2byte_head);
            return APM_L7_ANALYZE_FAIL;
        }

        /* 取得下一个token值 */
        if (bytebuff_remaining(p_st_data) < 2)
        {
            frdbg("need more data!\n");
            return APM_L7_ANALYZE_TODO;
        }
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_2byte_head, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            frdbg("Parse request faied!\n");
            return APM_L7_ANALYZE_FAIL;
        }
    }

    /* EOT作为结束token, 必须出现在末尾 */
    if (bytebuff_remaining(p_st_data) == 0)
    {
        /* 更新数据 */
        if (p_st_req->p_st_resultset)
        {
            frdb_set_resultset_req2(p_st_req->p_st_resultset
                                   , bytebuff_length(p_st_data)
                                   , &(p_st_fragment->st_first_timestamp)
                                   , &(p_st_fragment->st_end_timestamp));
        }
        informix_init_fragment(p_st_fragment);
        p_st_fragment->i_need_req_resp = INFORMIX_DIRECT_RESPONSE;

        switch (p_st_req->i_req_type)
        {
            /* 需要上报request数据 */
            case INFORMIX_MSG_TP_COMMAND:
            case INFORMIX_MSG_TP_EXECUTE:
            case INFORMIX_MSG_TP_BEGIN:
            case INFORMIX_MSG_TP_DBLIST:
            case INFORMIX_MSG_TP_XCOMMIT:
            case INFORMIX_MSG_TP_XROLLBACK:
            case INFORMIX_MSG_TP_PUT:
                i_ret = __informix_report_req(p_st_conn, p_st_private
                                             , p_st_hash_report);
                return i_ret;

           default:
               return APM_L7_ANALYZE_SUCC;
        }
    }
    else
    {
        frdbg("Parse request failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
}
